package mymath;

import chartUtils.Point;
import chartUtils.PointList;
import static java.lang.Math.cos;
import static java.lang.Math.sin;
import java.util.function.DoubleFunction;

public class Functions {

    // Class can not be instantiated
    private Functions() {
    }

    //some lambda functions
    public static DoubleFunction<Double> func01 = (double x) -> {
        return (1.0 / (1.5 + sin(x)));
    };

    public static DoubleFunction<Double> func02 = (double x) -> (sin(x) * cos(x));

    public static DoubleFunction<Double> func04 = (double x) -> (x - 5.0);

    public static DoubleFunction<Double> func03 = (double x) -> {
        Double y1 = Functions.func02.apply(x);
        Double y2 = Functions.func04.apply(x);
        Double y = y1 * y2;
        return y;
    };

    // recursion test - with a lambda function
    // my crude version of factorial as double
    public static DoubleFunction<Double> factorial = (double x) -> {
        Double factorialValue = Double.NaN;

        factorialValue = (x > 1.0001) ? (x * Functions.factorial.apply(x - 1.0)) : 1.0;

        return factorialValue;
    };

    // recursion - BUT NOT a lambda function!
    public static long fibonacci(int x) {
        if (x == 0 || x == 1) {
            return x;
        }
        return fibonacci(x - 1) + fibonacci(x - 2);
    }

    //---------------------------------------------------------------------
    public static PointList calcXYPointListForFunction(DoubleFunction<Double> fx, double x1, double x2, int numOfSteps) {

        PointList pointList = new PointList();

        double deltaX = (x2 - x1) / (numOfSteps - 1);
        double x = x1;
        double y;
        Point p;

        for (int j = 1; j <= numOfSteps; j++) {
            y = fx.apply(x);
            p = new Point(x, y);
            pointList.getPoints().add(p);
            System.out.println("j=" + j + "  x=" + x + " y=" + y);
            x = x + deltaX;
        }
        System.out.println("x1,x2: " + x1 + "/" + x2);

        return pointList;
    }

    //---------------------------------------------------------------------
    public static boolean hasPointListUndefinedValues(PointList pointList) {
        //check if NaN or +/- infinite
        boolean hasUndefinedValues = false;
        for (Point point : pointList.getPoints()) {
            if (!Double.isFinite(point.getY())) {
                hasUndefinedValues = true;
                System.out.println("undefined y-value at x=" + point.getX());
                break;
            }
        }
        return hasUndefinedValues;
    }

    //---------------------------------------------------------------------
    public static boolean _isDouble(String s) {
        boolean _isDouble = false;
        if (s != null) {
            try {
                Double tmp = new Double(s);
                _isDouble = true;
            } catch (NumberFormatException nfe) {
                //...
            }
        }
        return _isDouble;
    }
}
